package com.dingwen.treasure.core.util;


import io.swagger.annotations.ApiModelProperty;

import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.*;

/**
 * 　GenerateSqlFromEntityUtil
 * 　@author dingwen
 * 　@date 2022/9/16
 */
public class GenerateSqlFromEntityUtil {

    /**
     * javaProperty2SqlColumnMap
     */
    public static Map<String, String> javaProperty2SqlColumnMap = new HashMap<>();

    static {
        javaProperty2SqlColumnMap.put("Integer", "int4");
        javaProperty2SqlColumnMap.put("Short", "tinyint");
        javaProperty2SqlColumnMap.put("Long", "int8");
        javaProperty2SqlColumnMap.put("BigDecimal", "decimal(19,2)");
        javaProperty2SqlColumnMap.put("Double", "double precision not null");
        javaProperty2SqlColumnMap.put("Float", "float");
        javaProperty2SqlColumnMap.put("Boolean", "bit");
        javaProperty2SqlColumnMap.put("Timestamp", "datetime");
        javaProperty2SqlColumnMap.put("String", "VARCHAR(255)");
        javaProperty2SqlColumnMap.put("LocalDateTime", "timestamp(6)");
    }

    public static Field[] getAllFields(Class<?> clazz) {
        List<Field> fieldList = new ArrayList<>();
        while (clazz != null) {
            fieldList.addAll(new ArrayList<>(Arrays.asList(clazz.getDeclaredFields())));
            clazz = clazz.getSuperclass();
        }
        Field[] fields = new Field[fieldList.size()];
        return fieldList.toArray(fields);
    }


    /**
     * 创建表
     *
     * @param obj obj
     * @return {@link String}
     */
    public static String createTable(Class obj) {

        Field[] fields;
        fields = getAllFields(obj);
        String param;
        String column;
        StringBuilder stb;
        StringBuilder stbCommon = new StringBuilder();
        stb = new StringBuilder(50);

        String tableName = obj.getName();
        tableName = tableName.substring(tableName.lastIndexOf(".") + 1);
        tableName = getSqlNameByClassName(tableName);

        stb.append("create table ").append(tableName).append(" (\r\n");

        boolean firstId = true;

        for (Field f : fields) {
            column = f.getName();

            if ("serialVersionUID".equals(column)) {
                continue;
            }
            boolean isStatics = Modifier.isStatic(f.getModifiers());
            if (isStatics) {
                column = getSqlNameByStaticsClassName(column);
            } else {
                column = getSqlNameByClassName(column);
            }

            param = f.getType().getSimpleName();
            // 一般第一个是主键
            stb.append("    \"").append(column).append("\"");

            stb.append(" ");
            stb.append(javaProperty2SqlColumnMap.get(param));
            //类型转换 DEFAULT nextval('"+tableName+"_id_seq'::regclass)

            if (firstId) {
                stb.append(" NOT NULL ");
                firstId = false;
            }

            // 获取字段中包含fieldMeta的注解
            // 2、获取属性上的所有注释
            ApiModelProperty annotation = f.getAnnotation(ApiModelProperty.class);
            if (annotation != null) {
                stbCommon.append("COMMENT ON COLUMN \"public\".\"");
                stbCommon.append(tableName);
                stbCommon.append("\".\"");
                stbCommon.append(column);
                stbCommon.append("\" IS '");
                stbCommon.append(annotation.value());
                stbCommon.append("';");
                stbCommon.append("\n");
            }

            stb.append(",\r\n");
        }

        String sql;
        sql = stb.toString();

        // 去掉最后一个逗号
        int lastIndex = sql.lastIndexOf(",");
        sql = sql.substring(0, lastIndex) + sql.substring(lastIndex + 1);
        sql = sql + ");";
        System.out.println(sql);
        return stbCommon.toString();
    }

    public static String getSqlNameByClassName(String name) {
        StringBuilder result = new StringBuilder();
        if (name != null && name.length() > 0) {
            result.append(name.substring(0, 1).toLowerCase());
            // 循环处理其余字符
            for (int i = 1; i < name.length(); i++) {
                String s = name.substring(i, i + 1);
                // 在大写字母前添加下划线
                if (s.equals(s.toUpperCase()) && !Character.isDigit(s.charAt(0))) {
                    result.append("_");
                }
                // 其他字符直接转成大写
                result.append(s.toLowerCase());
            }
        }
        return result.toString();
    }


    /**
     * 被静态sql名字类名
     *
     * @param name 名字
     * @return {@link String}
     */
    public static String getSqlNameByStaticsClassName(String name) {
        return name.toLowerCase();
    }

    /**
     * 主要
     *
     * @param args arg游戏
     * @throws IOException ioexception
     */
    public static void main(String[] args) throws IOException {

        //String re = createTable(entity.class);
    }
}
